/**
 * @file QWF_Can.h
 * @brief QWF框架CAN通信模块头文件（封装HAL库CAN功能，支持多CAN总线管理）
 * @author WeiFan Qiu (qiuweifan0523@faxmail.com)
 * @version 1.0
 * @date 2025-08-07
 * 
 * @copyright Copyright (c) 2025  邱伟凡
 * 
 * @par 修改日志:
 * - 2025-08-07: 初始版本，定义CAN通信核心结构体与接口
 * 
 * @bug 待解决问题:
 * - 需验证多CAN总线并发通信时的邮箱冲突处理
 */
#ifndef QWF_CAN_H          // 头文件保护宏，防止重复包含
#define QWF_CAN_H          // 定义头文件标识，确保仅编译一次
#include "QWF_Custom_Ctrl.h"	// 自定义控制逻辑头文件（用户特定功能实现）
#include "stdint.h"        // 包含标准整数类型（如uint8_t、uint32_t）
/*定义can相关的适配名称,含前缀，不要前缀直接输空格*/
#if Chip_Type==Chip_STM32F405RGT6
#include "can.h"           // 包含HAL库CAN驱动头文件（定义CAN_HandleTypeDef等结构体）
#define can_stdld					StdId
#define get_can_type(prefix,data)	prefix##data
#define GET_CAN_TYPE(prefix,data)	prefix##data
#define can_add_tx_message(hcan,txhander,data,mailbox)	HAL_CAN_AddTxMessage(hcan,txhander,data,mailbox)

#elif Chip_Type==Chip_STM32H723VGT6
#include "fdcan.h"
#define can_stdld					Identifier
#define can_header_name()			hfdcan
#define get_can_type(prefix,data)	prefix##fd##data
#define GET_CAN_TYPE(prefix,data)	prefix##FD##data
#define can_add_tx_message(hcan,txhander,data,mailbox)	HAL_FDCAN_AddMessageToTxFifoQ(hcan,txhander,data)
#endif
#pragma pack(push, 1)      // 设置结构体1字节对齐（避免成员间填充，适配CAN通信8字节数据格式）
/**
 * @brief CAN发送数据类型（固定8字节，符合CAN协议数据帧格式）
 */
typedef uint8_t qwf_can_data_tx_t[8];

/**
 * @brief QWF框架CAN对象结构体（封装单个CAN总线的配置与运行状态）
 */
typedef struct {
    GET_CAN_TYPE( ,CAN_HandleTypeDef)* hcan;  // HAL库CAN句柄指针（关联具体CAN硬件实例，如&hcan1）

    struct {  // CAN发送相关配置
        struct {  // 发送头（包含标识符、数据长度等）
            struct {
                GET_CAN_TYPE( ,CAN_TxHeaderTypeDef) id200;  // 标识符0x200的发送头（用于C620等电机）
                GET_CAN_TYPE( ,CAN_TxHeaderTypeDef) id1ff;  // 标识符0x1ff的发送头（用于旧版GM6020等）
                GET_CAN_TYPE( ,CAN_TxHeaderTypeDef) id2ff;  // 标识符0x2ff的发送头（用于旧版GM6020等）
                GET_CAN_TYPE( ,CAN_TxHeaderTypeDef) id1fe;  // 标识符0x1fe的发送头（用于新版GM6020电流模式）
                GET_CAN_TYPE( ,CAN_TxHeaderTypeDef) id2fe;  // 标识符0x2fe的发送头（用于新版GM6020电流模式）
            } DJI;  // 大疆电调专用发送头（按标识符分类）
        } header;

        struct {  // 发送邮箱（存储CAN硬件分配的邮箱编号）
            struct {
                uint32_t id200;  // 标识符0x200对应的邮箱号
                uint32_t id1ff;  // 标识符0x1ff对应的邮箱号
                uint32_t id2ff;  // 标识符0x2ff对应的邮箱号
                uint32_t id1fe;  // 标识符0x1fe对应的邮箱号
                uint32_t id2fe;  // 标识符0x2fe对应的邮箱号
            } DJI;  // 大疆电调专用邮箱（按标识符分类）
        } mailbox;

        struct {  // 发送数据缓冲区（存储待发送的8字节数据）
            struct {
                uint8_t id200[8];  // 标识符0x200的数据缓冲区（每个电机占2字节）
                uint8_t id1ff[8];  // 标识符0x1ff的数据缓冲区
                uint8_t id2ff[8];  // 标识符0x2ff的数据缓冲区
                uint8_t id1fe[8];  // 标识符0x1fe的数据缓冲区
                uint8_t id2fe[8];  // 标识符0x2fe的数据缓冲区
            } DJI;  // 大疆电调专用数据缓冲区（按标识符分类）
        } data;

        struct {  // 发送标识符使用标记（防止同一标识符重复配置）
            struct {
                _Bool id200;  // 标识符0x200是否已被使用
                _Bool id1ff;  // 标识符0x1ff是否已被使用
                _Bool id2ff;  // 标识符0x2ff是否已被使用
                _Bool id1fe;  // 标识符0x1fe是否已被使用
                _Bool id2fe;  // 标识符0x2fe是否已被使用
            } DJI;  // 大疆电调专用标识符标记（按标识符分类）
        } StdId_use;
    } tx;  // CAN发送配置

    struct {  // CAN接收相关配置
        GET_CAN_TYPE( ,CAN_RxHeaderTypeDef) header;  // 接收头（包含标识符、数据长度等）
        struct {  // 接收标识符使用标记（过滤非目标标识符）
            struct {
                _Bool id204[8];  // 标识符0x204+ID（ID 1-8）是否启用接收（用于GM6020反馈）
                _Bool id200[8];  // 标识符0x200+ID（ID 1-8）是否启用接收（用于C620反馈）
                _Bool id2ff[8];  // 标识符0x2ff+ID（ID 1-8）是否启用接收（用于旧版GM6020反馈）
                _Bool id1fe[8];  // 标识符0x1fe+ID（ID 1-8）是否启用接收（用于新版GM6020反馈）
                _Bool id2fe[8];  // 标识符0x2fe+ID（ID 1-8）是否启用接收（用于新版GM6020反馈）
            } DJI;  // 大疆电调专用接收标识符标记（按标识符分类）
        } StdId_use;
        uint8_t data[8];  // 接收数据缓冲区（存储接收到的8字节数据）
    } rx;  // CAN接收配置
} QWF_can_obj_t;

/**
 * @brief QWF框架CAN全局管理结构体（包含3个CAN总线实例，对应CAN1/CAN2/CAN3）
 */
typedef struct {
    QWF_can_obj_t can1;  // CAN1总线对象
    QWF_can_obj_t can2;  // CAN2总线对象
    QWF_can_obj_t can3;  // CAN3总线对象（若硬件支持）
} QWF_CAN_t;

extern QWF_CAN_t* qwf_can;  // 全局CAN管理对象指针（外部可访问）

/**
 * @brief 获取指取qwf_can结构体里的的对应数据
 * @param canx: CAN总线编号（1/2/3）
 * @param elec_ctrl_id: 电调标识符（如id204、id200等）
 * @return qwf_can结构体里的数据
 */
#define get_qwf_can_obj(canx)                               (qwf_can->can##canx)
#define get_qwf_can_hcan(canx)                              (get_qwf_can_obj(canx).hcan)
#define get_qwf_can_rx_can(canx)                            (get_qwf_can_obj(canx).rx.header)  
#define get_qwf_can_data_rx(canx)                           (get_qwf_can_obj(canx).rx.data) 
#define get_qwf_can_data_tx(canx,elec_ctrl_id)              (get_qwf_can_obj(canx).tx.data.elec_ctrl_id)
#define get_qwf_can_mailbox(canx,elec_ctrl_id)              (get_qwf_can_obj(canx).tx.mailbox.elec_ctrl_id)
#define get_qwf_can_tx_header(canx,elec_ctrl_id)            (get_qwf_can_obj(canx).tx.header.elec_ctrl_id)
#define get_qwf_can_tx_StdId_use(canx,elec_ctrl_id)     	(get_qwf_can_obj(canx).tx.StdId_use.elec_ctrl_id)
#define get_qwf_can_rx_StdId_use(canx,elec_ctrl_id)     	(get_qwf_can_obj(canx).tx.StdId_use.elec_ctrl_id)
/**
 * @brief 发送CAN数据帧（通用接口）
 * @param StdId: 标准标识符（11位）
 * @param Mailbox: 硬件邮箱编号（0-2）				
 * @param Data: 待发送的8字节数据				
 * @param hcan: CAN句柄指针（关联具体CAN硬件）	
 */
void Can_Send_Data(uint32_t StdId,uint32_t Mailbox ,uint8_t Data[8],GET_CAN_TYPE( ,CAN_HandleTypeDef)*hcan);
/**
 * @brief 初始化CAN总线（配置HAL句柄、邮箱、标识符等）
 */
void Can_Init(void);
#pragma pack(pop)  // 恢复默认结构体对齐方式
#endif  // QWF_CAN_H
